
package com.drei.wolke.server.oauth2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.stereotype.Component;

/**
 * @author 作者 owen E-mail: 624191343@qq.com
 * @version 创建时间：2017年11月12日 上午22:57:51
 */
@Configuration
public class OAuth2ServerConfig {

 
	/**
	 * @author 作者 owen E-mail: 624191343@qq.com
	 * @version 创建时间：2017年10月30日 上午9:45:12 类说明 默认token存储在内存中
	 *          DefaultTokenServices默认处理
	 */
	@Component
	@Configuration
	@EnableAuthorizationServer
	public static class UnieapAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
		/**
		 * 注入authenticationManager 来支持 password grant type
		 */
		@Autowired
		private AuthenticationManager authenticationManager;

		@Autowired
		private UserDetailsService userDetailsService;
		@Autowired(required = false)
		private TokenStore redisTokenStore;

		@Autowired(required = false)
		private TokenStore jwtTokenStore;
		@Autowired(required = false)
		private JwtAccessTokenConverter jwtAccessTokenConverter;

		public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

			if (jwtTokenStore != null) {
				endpoints.tokenStore(jwtTokenStore).authenticationManager(authenticationManager)
						.userDetailsService(userDetailsService); // 支持
				// password
				// grant
				// type;
			} else if (redisTokenStore != null) {
				endpoints.tokenStore(redisTokenStore).authenticationManager(authenticationManager)
						.userDetailsService(userDetailsService); // 支持
				// password
				// grant
				// type;
			}

			if (jwtAccessTokenConverter != null) {
				endpoints.accessTokenConverter(jwtAccessTokenConverter);
			}

		}

		// 配置应用名称 应用id
		@Override
		public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
			clients.inMemory().withClient("neusoft1").secret("neusoft1")
					.authorizedGrantTypes("authorization_code", "password", "refresh_token").scopes("all")
					.accessTokenValiditySeconds(1200)
	                .refreshTokenValiditySeconds(50000)
					.and().withClient("neusoft2").secret("neusoft2")
					.authorizedGrantTypes("authorization_code", "password", "refresh_token").scopes("all")
					.accessTokenValiditySeconds(1200)
	                .refreshTokenValiditySeconds(50000)
					;
		}

		@Override
		public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {

			security.tokenKeyAccess("isAuthenticated()").checkTokenAccess("isAuthenticated()")
					.allowFormAuthenticationForClients();

			// security.allowFormAuthenticationForClients();
			//// security.tokenKeyAccess("permitAll()");
			// security.tokenKeyAccess("isAuthenticated()");
		}

	}

	@Component
	@Configuration
	@EnableResourceServer
	public static class UnieapResourceServerConfig extends ResourceServerConfigurerAdapter {

		@Autowired
		private UserDetailsService userDetailsService;
		@Autowired(required = false)
		private TokenStore redisTokenStore;

		@Autowired(required = false)
		private TokenStore jwtTokenStore;
		@Autowired(required = false)
		private JwtAccessTokenConverter jwtAccessTokenConverter;

		@Override
		public void configure(ResourceServerSecurityConfigurer resources) throws Exception {

			if (jwtTokenStore != null) {
				resources.tokenStore(jwtTokenStore) ;
			} else if (redisTokenStore != null) {
				resources.tokenStore(redisTokenStore) ;
			}

		}

		@Override
		public void configure(HttpSecurity http) throws Exception {

			// http.httpBasic() //默认配置
			// 用表单登录
			http.userDetailsService(userDetailsService).formLogin() 
			// 对请求授权
			.and().authorizeRequests() 
			//所有需要restful保护的资源都需要加入到这个requestMatchers，加入到的资源作为资源服务器保护的资源
			.and() .requestMatchers() .antMatchers("/**/user","/user" ) .and().authorizeRequests()
			.antMatchers("/session/invalid","/login","/**/login") .permitAll()
			.antMatchers("/**/user/","/user" ,
							     "/**/hello","/hello",
							     "/**/index.html","/index.html",
							     "/**/oauth/authorize","/oauth/authorize",
							     "/**/oauth/token","/oauth/token" ,
							     "/**/test111","/test111" 
								).authenticated()
					.anyRequest()
					.authenticated() // 所有的请求认证
					.and().csrf().disable() // 关闭Could not verify the provided
											// CSRF
											// token because your session was
											// not
											// found
			;
		}

	}

	/*
	 * WebSecurityConfigurerAdapter的过滤器比ResourceServerConfigurerAdapter钱
	 * UsernamePasswordAuthenticationFilter > BasicAuthenticationFilter >
	 * OAuth2AuthenticationProcessingFilter
	 */
	@Component
	@Configuration
	@EnableWebSecurity
	// @Order(Integer.MAX_VALUE)
	public static class UnieapSecurityConfig extends WebSecurityConfigurerAdapter {

		@Autowired
		private UserDetailsService userDetailsService;
		@Autowired
		private PasswordEncoder passwordEncoder;

		/**
		 * 需要配置这个支持password模式 support password grant type
		 * 
		 * @return
		 * @throws Exception
		 */
		@Override
		@Bean
		public AuthenticationManager authenticationManagerBean() throws Exception {
			return super.authenticationManagerBean();
		}

		@Override
		protected void configure(AuthenticationManagerBuilder auth) throws Exception {
			auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
		}

		@Override
		protected void configure(HttpSecurity http) throws Exception {
			http.formLogin().and().csrf().disable().authorizeRequests()
			//页面请求处理
			.and() .authorizeRequests()
					.antMatchers(
							"/**/login" ,"/login", "/hello" ,
							"/**/oauth/authorize","/oauth/authorize",
						     "/**/oauth/token","/oauth/token" ,
						     "/**/getUserFromToken" ,"/getUserFromToken"
					 ).permitAll()
					.anyRequest().authenticated()
					.and().logout().permitAll();
		}

	}
}
